﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace UniSender
{
    using Expando = Dictionary<string, object>;
    using IExpando = IDictionary<string, object>;

    public class ImportSubscriber : Subscriber
    {
        public virtual bool Delete { get; set; }
    }

    public class ImportConfig
    {
        private List<ImportSubscriber> contacts = new List<ImportSubscriber>();

        public IList<ImportSubscriber> Contacts
        {
            get { return contacts; }
        }
        public virtual bool? DoubleOptIn { get; set; }
        public virtual bool? OverwriteTags { get; set; }
        public virtual bool? OverwriteLists { get; set; }
        public virtual bool Force { get; set; }

        public ImportConfig(params ImportSubscriber[] contacts)
        {
            if (contacts != null && contacts.Length > 0)
                this.contacts.AddRange(contacts);
        }

        private void AddData(IExpando data, int index, string field, object value)
        {
            IExpando sub = data.ContainsKey(field) ? data[field] as IExpando : null;
            if (sub == null)
                data[field] = sub = new Expando();
            sub[index.ToString()] = value;
        }

        private void AddData(IExpando data, int index, Contact contact)
        {
            string field = contact is EmailContact ? "email" : "phone";
            AddData(data, index, field, contact.Value);
            field += "_";
            Action<string, object> AddValue = (key, value) => {
                AddData(data, index, field + key, value);
            };
            AddValue("status", contact.Status.Stringify());
            AddValue("availability", contact.Availability.Stringify());
            AddValue("add_time", contact.AddTime.Stringify());
            AddValue("request_ip", contact.RequestIP);
            
            if (contact.Subscriptions != null && contact.Subscriptions.Length > 0)
            {
                AddValue("list_ids", contact.Subscriptions.Select(s => s.ListId).ToArray());
                AddValue("subscribe_times", contact.Subscriptions.Select(s => s.Time.Stringify()).ToArray());
            }
            AddValue("unsubscribed_list_ids", contact.UnsubscribedListIds);
            AddValue("excluded_list_ids", contact.ExcludedListIds);

        }

        public virtual IExpando Serialize()
        {
            Expando args = new Expando();

            // serialize contacts
            var data = new Expando();
            int i = 0;
            foreach (var contact in contacts)
            {
                if (contact.Email != null)
                {
                    AddData(data, i, contact.Email);
                    AddData(data, i, "email_confirm_ip", contact.Email.ConfirmIP);
                    AddData(data, i, "email_confirm_time", contact.Email.ConfirmTime.Stringify());
                }
                if (contact.Phone != null)
                {
                    AddData(data, i, contact.Phone);
                }
                if (contact.Delete)
                    AddData(data, i, "delete", 1);
                AddData(data, i, "tags", contact.Tags);
                foreach (var custom in contact.Custom)
                    AddData(data, i, custom.Key, custom.Value);
                ++i;
            }
            i = 0;
            foreach (var field in data)
            {
                args[string.Format("field_names[{0}]", i)] = field.Key;
                foreach (var item in field.Value as IExpando)
                    args[String.Format("data[{0}][{1}]", item.Key, i)] = item.Value;
                ++i;
            }

            if (DoubleOptIn != null)
                args["double_optin"] = DoubleOptIn.Value ? 1 : 0;
            if (OverwriteTags != null)
                args["overwrite_tags"] = OverwriteTags.Value ? 1 : 0;
            if (OverwriteLists != null)
                args["overwrite_lists"] = OverwriteLists.Value ? 1 : 0;
            if (Force)
                args["force_import"] = 1;

            return args;
        }
    }
}
